package com.theorydance.esoperator.utils;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import java.util.Map;

/**
 * 针对ak/sk进行验证的工具
 * @Author grand_ranfs
 * @Date 2023/11/16 10:43
 */
public class SignUtilServer {

    /**
     * 验证请求是否有效(服务器端用)
     * @return 是否有效(方便测试我用Boolean,可根据业务需要，返回对应错误信息，不一定用Boolean)
     */
    public static Boolean checkReqInfo(Map<String, Object> reqHeader, Map<String, Object> reqParam) {
        // 1.没有header ： 无效请求
        if (MapUtil.isEmpty(reqHeader)) return false;

        // 2.没有ts（请求时间戳）：无效请求
        Long ts = MapUtil.get(reqHeader, "ts", Long.class);
        if (ts == null) return false;

        // 3.超过20分钟：无效请求
        if (System.currentTimeMillis() - ts > 20 * 60 * 1000) return false;

        /*4.如果带有请求唯一标识，则需要先验证此标识是否已经被处理过，防止重复请求（不一定每个项目都要求考虑此项，这里只是一个思路，
         * 需要的可以加上）；如果处理过，返回false,如果没处理过，则把这个唯一标识存到redis(随意)
         */
        String nonce = MapUtil.getStr(reqHeader, "nonce");
        if (StrUtil.isNotBlank(nonce)) {
            // 判断是否重复请求
            Boolean isRepeat = isRepeatNonce(nonce);
            if (isRepeat) {
                // 4.1重复请求：无效请求
                return false;
            } else {
                // 4.2标记此请求正在被处理或已被处理
                saveNonceToRedis(nonce);
            }
        }

        // 5.appId是否存在（用户是否存在）,不存在则算无效请求
        String appId = MapUtil.getStr(reqHeader, "appId");
        if(StrUtil.isBlank(appId)) return false;

        // 5.1去库中或配置中获取appId对应的appSecret  (这里方便测试，先写死)
        String appSecret = getSkByAK(appId);
        // 5.2没有此appId对应信息：无效请求
        if(StrUtil.isBlank(appSecret)) return false;

        // 6.sign验证
        // 6.1 没传sign：无效请求
        String sign = MapUtil.getStr(reqHeader, "sign","");
        if(StrUtil.isBlank(sign)) return false;
        //6.2最后验证sign值（按约定的sign计算方式，服务器端也算出一个sign，将这里计算出的sign和请求中的sign比较，是否一致）
        String srvSign = SignUtilCore.getSign(appId, appSecret, ts, nonce, reqParam);
        System.out.println("sign = " + sign);
        System.out.println("srvSign = " + srvSign);

        // 目前能想到的安全验证就这些，或许大家还能想到其他验证，让接口更加安全
        return sign.equalsIgnoreCase(srvSign);
    }

    private static String getSkByAK(String appId) {
        return "9ZLEzugQHfQd11vS8pd68lxzA";
    }

    private static void saveNonceToRedis(String nonce) {
        System.out.println("将请求唯一nonce保存到redis中，nonce = " + nonce);
    }

    private static Boolean isRepeatNonce(String nonce) {
        return false;
    }


}

